package cn.schoolwow.util.domain.crypto.cipher.aes;

import cn.schoolwow.quickflow.QuickFlow;
import cn.schoolwow.quickflow.QuickFlowBuilder;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.util.module.crypto.cipher.aes.domain.AESCipherOption;
import cn.schoolwow.util.module.crypto.cipher.aes.flow.AESDecryptFlow;
import cn.schoolwow.util.module.crypto.cipher.aes.flow.AESEncryptFlow;
import cn.schoolwow.util.module.crypto.cipher.aes.flow.CheckAESCipherOption;
import cn.schoolwow.util.module.crypto.cipher.aes.flow.GenerateSecretKeyFlow;

import java.security.SecureRandom;
import java.util.Base64;

public class AESCipher {
    private AESCipherOption aesCipherOption = new AESCipherOption();

    private QuickFlow quickFlow = QuickFlowBuilder.newInstance()
            .putContextThreadLocalInstanceData(aesCipherOption);

    /**
     * 生成AES算法密钥
     * @param aesSecretKeyType 密钥类型
     * */
    public static String generateSecretKey(AESSecretKeyType aesSecretKeyType){
        FlowContext flowContext = QuickFlowBuilder.startFlow(new GenerateSecretKeyFlow())
                .putCurrentCompositeFlowData("keyLength", aesSecretKeyType.n)
                .execute();
        String secretKey = flowContext.getData("secretKey", String.class);
        return secretKey;
    }

    /**生成随机向量*/
    public static String generateRandomIV() {
        SecureRandom random = new SecureRandom();
        byte[] iv = new byte[16];
        random.nextBytes(iv);
        String ivString = Base64.getEncoder().encodeToString(iv);
        return ivString;
    }

    /**创建AES算法对象*/
    public static AESCipher newCipher(String secretKey){
        AESCipher aesCipher = new AESCipher();
        aesCipher.aesCipherOption.secretKey = secretKey;
        return aesCipher;
    }

    /**指定明文或者密文*/
    public AESCipher data(String data){
        aesCipherOption.data = data;
        return this;
    }

    /**指定向量*/
    public AESCipher iv(String iv){
        aesCipherOption.iv = iv;
        return this;
    }

    /**指定模式*/
    public AESCipher mode(String mode){
        aesCipherOption.mode = mode;
        return this;
    }

    /**指定padding算法*/
    public AESCipher padding(String padding){
        aesCipherOption.padding = padding;
        return this;
    }

    /**加密*/
    public String encrypt(){
        FlowContext flowContext = quickFlow.startFlow(new CheckAESCipherOption())
                .next(new AESEncryptFlow())
                .execute();
        String encryptText = flowContext.checkData("string", String.class);
        return encryptText;
    }

    /**解密*/
    public String decrypt(){
        FlowContext flowContext = quickFlow.startFlow(new CheckAESCipherOption())
                .next(new AESDecryptFlow())
                .execute();
        String plainText = flowContext.checkData("string", String.class);
        return plainText;
    }
}
